import { message } from "antd";
import qs from 'qs'

//核心方法
const http = function(config){
    if(Object.prototype.toString.call(config) !== '[object Object]') config = {};
    config = Object.assign({
        url:'',
        method:'GET',
        credentials:'include',
        headers:null,
        body:null,
        params:null,
        responseType: 'json',
        signal:null
    },config)
    if(!config.url) throw new TypeError('url must be required');
    if(Object.prototype.toString.call(config.headers) !== '[object Object]') config.headers = {};
    if(config.params !== null && Object.prototype.toString.call(config.params) !== '[object Object]') config.params = null;
    let {url,method,credentials,headers,body,params,responseType,signal} = config;
    //处理问号传参
    if(params){
        url += `${url.includes('?')?'&':'?'}${qs.stringify(params)}`
    }
    //处理请求主体信息：按照我们后台要求，如果传递的是一个普通对象，我们要把其设置为urlencoded格式[设置请求头]？
    if(Object.prototype.toString.call(body) === '[object Object]'){
        body = qs.stringify(body);
        headers['Content-Type'] = 'application/x-www-form-urlencoded';
    }
    //类似于axios中的请求拦截器：每一个请求，递给服务器相同的内容可以在这里处理[例如：token]
    let token = localStorage.getItem('tk');
    if(token) headers['authorization'] = token;

    //发送请求
    method = method.toUpperCase();
    config = {
        method,
        credentials,
        headers,
        cache:'no-cache',
        signal
    };
    if(/^(PUT|POST|PATCH)$/i.test(method) && body) config.body = body;
    return fetch(url,config)
    .then(response => {
        //进入then的时候，不一定是请求成功[因为状态码是各种情况]
        if (/^(2|3)\d{2}$/.test(response.status)) {
            //请求成功：根据预设的方式，获取需要的值
            let result;
            switch(responseType.toLowerCase()){
                case 'text':
                    result = response.text();
                    break;
                case 'arraybuffer':
                    result = response.arrayBuffer();
                    break;
                case 'blob':
                    result = response.blob();
                    break;
                default:
                    result = response.json();
            }
            return result
        }
        return Promise.reject({
            code: -100,
            state: response.status,
            stateText: response.statusText
        })
    }).catch(reason=>{
        //失败的统一提示
        if(reason && reason === 'object'){
            let {code,status} = reason;
            if(code === -100){
                switch(+status){
                    case 400:
                        message.error('请求参数出现问题');
                        break;
                }
            }else if(code === 20){
                message.error('请求被中断了～');
            }else{
                message.error('当前网络繁忙，请您稍后再试～');
            }
        }else{
            message.error('当前网络繁忙，情您稍后再试～');
        }
        return Promise.reject(reason);//统一处理完毕后，在组件中获取到的依然还是失败
    })
}
//快捷方法
let arry1 = ['GET','HEAD','DELETE','OPTIONS']
arry1.forEach(item=>{
    http[item.toLowerCase()] = function(url,config){
        if(Object.prototype.toString.call(config) !== '[object Object]') config = {}
        config['method'] = item;
        config['url'] = url
        return http(config)
    }
})
let arry2 = ['POST','PUT','PATCH']
arry2.forEach(item=>{
    http[item.toLowerCase()] = function(url,body,config){
        if(Object.prototype.toString.call(config) !== '[object Object]') config = {}
        config['body'] = body
        config['method'] = item;
        config['url'] = url
        return http(config)
    }
})
export default http